package com.didi.gulimall.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.didi.gulimall.common.constant.BizCodeEnume;
import com.didi.gulimall.common.constant.MemberConstant;
import com.didi.gulimall.common.to.OrderSuccessVo;
import com.didi.gulimall.common.utils.HttpUtils;
import com.didi.gulimall.common.utils.PageUtils;
import com.didi.gulimall.common.utils.Query;
import com.didi.gulimall.common.utils.R;
import com.didi.gulimall.member.dao.MemberDao;
import com.didi.gulimall.member.entity.MemberChangeHistoryEntity;
import com.didi.gulimall.member.entity.MemberEntity;
import com.didi.gulimall.member.entity.MemberLevelEntity;
import com.didi.gulimall.member.service.MemberChangeHistoryService;
import com.didi.gulimall.member.service.MemberLevelService;
import com.didi.gulimall.member.service.MemberService;
import com.didi.gulimall.member.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;


@Service("memberService")
@Slf4j
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {
    @Autowired
    private MemberLevelService memberLevelService;

    @Autowired
    private MemberChangeHistoryService memberChangeHistoryService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public R registered(MemberRegistVo memberRegistVo) {
        if (checkDuplicatefields("username", memberRegistVo.getUserName())) {
            return R.error(BizCodeEnume.USER_EXIST_EXCEPTION.getMsg());
        } else if (checkDuplicatefields("mobile", memberRegistVo.getPhone())) {
            return R.error(BizCodeEnume.PHONE_EXIST_EXCEPTION.getMsg());
        }
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setMobile(memberRegistVo.getPhone());
        memberEntity.setUsername(memberRegistVo.getUserName());
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode(memberRegistVo.getPassword());
        memberEntity.setPassword(encode);

        memberEntity.setNickname(UUID.randomUUID().toString().substring(0, 10));
        MemberLevelEntity memberLevelEntity = memberLevelService.getDefaultLevel();
        memberEntity.setLevelId(memberLevelEntity.getId());
        memberEntity.setGrowth(MemberConstant.DEFAULT_GROWTH_VALUE);
        memberEntity.setSourceType(MemberConstant.UserSource.WEBSITE_REGISTRATION.getCode());
        memberEntity.setStatus(MemberConstant.USED);
        memberEntity.setIntegration(MemberConstant.DEFAULT_INTEGRATION);
        memberEntity.setCreateTime(new Date());

        baseMapper.insert(memberEntity);
        return R.ok();
    }

    @Override
    public R login(MemberLoginVo memberLoginVo) {
        MemberEntity member = getMemberByNameOrPhone(memberLoginVo);
        if (member == null) {
            return R.error(BizCodeEnume.USER_DOES_NOT_EXIST.getMsg());
        }
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (!bCryptPasswordEncoder.matches(memberLoginVo.getPassword(), member.getPassword())) {
            return R.error(BizCodeEnume.INCORRECT_PASSWORD.getMsg());
        }
        return R.ok().put("user", member);
    }

    @Override
    public R oauthweibologin(SocialUser socialUser) throws Exception {
        String uid = socialUser.getUid();
        MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("uid", uid));
        if (memberEntity == null) {
            memberEntity = new MemberEntity();
            Map<String, String> query = new HashMap<>();
            query.put("access_token", socialUser.getAccess_token());
            query.put("uid", socialUser.getUid());
            HttpResponse res = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", "get", new HashMap<String, String>(16), query);
            if (res.getStatusLine().getStatusCode() == HttpStatus.OK.value()) {
                String json = EntityUtils.toString(res.getEntity());
                log.info("微博用户数据：{}", json);
                WeiboResVo weiboResVo = JSON.parseObject(json, WeiboResVo.class);
                memberEntity.setNickname(weiboResVo.getName());
                MemberLevelEntity memberLevelEntity = memberLevelService.getDefaultLevel();
                memberEntity.setLevelId(memberLevelEntity.getId());
                memberEntity.setGrowth(MemberConstant.DEFAULT_GROWTH_VALUE);
                memberEntity.setSourceType(MemberConstant.UserSource.WEBSITE_REGISTRATION.getCode());
                memberEntity.setStatus(MemberConstant.USED);
                memberEntity.setIntegration(MemberConstant.DEFAULT_INTEGRATION);
                memberEntity.setCreateTime(new Date());
                memberEntity.setGender(weiboResVo.getGender().equals(MemberConstant.WEIBO_GENDER_MALE) ? 1 : 0);
                memberEntity.setHeader(weiboResVo.getProfileImageUrl());
                memberEntity.setUid(socialUser.getUid());
                baseMapper.insert(memberEntity);
            }
        }
        memberEntity.setPassword(null);
        return R.ok().put("user", memberEntity);
    }


    @Override
    public void addMemberGI(Long memberId, Integer growth, Integer integration) {
        baseMapper.addMemberGI(memberId, growth, integration);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R subjectPoint(List<MemberOrderPointsVo> memberOrderPointsVos, HttpSession session) {
        for (MemberOrderPointsVo memberOrderPointsVo : memberOrderPointsVos) {
            Integer integration = 0;
            Integer growth = 0;
            List<MemberChangeHistoryEntity> changeHistoryEntities = new ArrayList<>();
            if (memberOrderPointsVo.getGrowth() != null && memberOrderPointsVo.getGrowth() > 0) {
                MemberChangeHistoryEntity memberChangeHistoryEntity = subjectHistory(memberOrderPointsVo.getGrowth(), memberOrderPointsVo.getMemberId(), memberOrderPointsVo.getOrderSn(), MemberConstant.GROWTH_VALUE, MemberConstant.GROWTH_VALUE_SUBJECT_NOTE);
                changeHistoryEntities.add(memberChangeHistoryEntity);
                growth = memberOrderPointsVo.getGrowth();
            }
            if (memberOrderPointsVo.getIntegration() != null && memberOrderPointsVo.getIntegration() > 0) {
                MemberChangeHistoryEntity memberChangeHistoryEntity = subjectHistory(memberOrderPointsVo.getGrowth(), memberOrderPointsVo.getMemberId(), memberOrderPointsVo.getOrderSn(), MemberConstant.INTEGRATION, MemberConstant.INTEGRATION_SUBJECT_NOTE);
                changeHistoryEntities.add(memberChangeHistoryEntity);
                integration = memberOrderPointsVo.getIntegration();
            }
            memberChangeHistoryService.saveBatch(changeHistoryEntities);
            subjectMemberGI(memberOrderPointsVo.getMemberId(), growth, integration);
//        session.setAttribute(AuthServerConstant.LOGIN_USER, getById(memberOrderPointsVo.getMemberId()));
        }
        return R.ok();
    }

    public void subjectMemberGI(Long memberId, Integer growth, Integer integration) {
        baseMapper.subjectMemberGI(memberId, growth, integration);
    }

    @Override
    public void addMemberGI(OrderSuccessVo orderSuccessVo) {
        QueryWrapper<MemberChangeHistoryEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_sn", orderSuccessVo.getOrderSn())
                .eq("look_status", MemberConstant.UNLOCK);
        int count = memberChangeHistoryService.count(queryWrapper);
        if (count > 0) {
            return;
        }
        List<MemberChangeHistoryEntity> memberChangeHistoryEntities = new ArrayList<>();
        Integer integration = 0;
        Integer growth = 0;
        if (orderSuccessVo.getGrowth() != null && orderSuccessVo.getGrowth() > 0) {
            MemberChangeHistoryEntity memberChangeHistoryEntity = addHistory(orderSuccessVo.getGrowth(), orderSuccessVo.getMemberId(), orderSuccessVo.getOrderSn(), MemberConstant.GROWTH_VALUE, MemberConstant.GROWTH_VALUE_ADD_NOTE);
            memberChangeHistoryEntities.add(memberChangeHistoryEntity);
            growth = orderSuccessVo.getGrowth();
        }
        if (orderSuccessVo.getIntegration() != null && orderSuccessVo.getIntegration() > 0) {
            MemberChangeHistoryEntity memberChangeHistoryEntity = addHistory(orderSuccessVo.getGrowth(), orderSuccessVo.getMemberId(), orderSuccessVo.getOrderSn(), MemberConstant.INTEGRATION, MemberConstant.INTEGRATION_ADD_NOTE);
            memberChangeHistoryEntities.add(memberChangeHistoryEntity);
            integration = orderSuccessVo.getIntegration();
        }
        memberChangeHistoryService.saveBatch(memberChangeHistoryEntities);
        addMemberGI(orderSuccessVo.getMemberId(), growth, integration);
        // TODO 发消息 第三方已经退了 查询登录
    }

    private MemberEntity getMemberByNameOrPhone(MemberLoginVo memberLoginVo) {
        MemberEntity member = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("username", memberLoginVo.getLoginacct()));
        if (member == null) {
            member = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("mobile", memberLoginVo.getLoginacct()));
        }
        return member;
    }

    private boolean checkDuplicatefields(String column, String key) {
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq(column, key));
        return count > 0;
    }

    private MemberChangeHistoryEntity addHistory(Integer changeCount, Long memberId, String orderSn, Integer type, String node) {
        MemberChangeHistoryEntity memberChangeHistoryEntity = new MemberChangeHistoryEntity();
        memberChangeHistoryEntity.setChangeCount("+" + changeCount);
        memberChangeHistoryEntity.setCreateTime(new Date());
        memberChangeHistoryEntity.setMemberId(memberId);
        memberChangeHistoryEntity.setNote(node);
        memberChangeHistoryEntity.setType(type);
        memberChangeHistoryEntity.setOrderSn(orderSn);
        memberChangeHistoryEntity.setSourceType(MemberConstant.SHOPPING_SOURCE);
        memberChangeHistoryEntity.setLookStatus(MemberConstant.LOCKING);
        memberChangeHistoryEntity.setIsDelete(MemberConstant.UNDELETE);
        return memberChangeHistoryEntity;
    }

    private MemberChangeHistoryEntity subjectHistory(Integer changeCount, Long memberId, String orderSn, Integer type, String node) {
        MemberChangeHistoryEntity memberChangeHistoryEntity = new MemberChangeHistoryEntity();
        memberChangeHistoryEntity.setChangeCount("-" + changeCount);
        memberChangeHistoryEntity.setCreateTime(new Date());
        memberChangeHistoryEntity.setMemberId(memberId);
        memberChangeHistoryEntity.setNote(node);
        memberChangeHistoryEntity.setType(type);
        memberChangeHistoryEntity.setOrderSn(orderSn);
        memberChangeHistoryEntity.setSourceType(MemberConstant.SHOPPING_SOURCE);
        memberChangeHistoryEntity.setLookStatus(MemberConstant.LOCKING);
        memberChangeHistoryEntity.setIsDelete(MemberConstant.UNDELETE);
        return memberChangeHistoryEntity;
    }

    public String parseTimeZone(String dateString) {
        String FORMAT_STRING = "yyyy-MM-dd HH:mm:ss";
        String FORMAT_STRING2 = "EEE MMM dd HH:mm:ss z yyyy";
        String[] REPLACE_STRING = new String[]{"GMT+0800", "GMT+08:00"};
        String SPLIT_STRING = "(中国标准时间)";
        try {
            dateString = dateString.split(Pattern.quote(SPLIT_STRING))[0].replace(REPLACE_STRING[0], REPLACE_STRING[1]);
            //转换为date
            SimpleDateFormat sf1 = new SimpleDateFormat(FORMAT_STRING2, Locale.ENGLISH);
            Date date = sf1.parse(dateString);
            return new SimpleDateFormat(FORMAT_STRING).format(date);
        } catch (Exception e) {
            throw new RuntimeException("时间转化格式错误" + "[dateString=" + dateString + "]" + "[FORMAT_STRING=" + FORMAT_STRING + "]");
        }
    }
}